#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.common;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.config.annotation.Reference;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;

import uyun.bird.tenant.api.UserService;
import uyun.bird.tenant.api.entity.User;

@Component
public class ApiSupport {
	private static final Logger logger = LoggerFactory.getLogger(ApiSupport.class);
	private static Cache<String, User> apikeyCache = CacheBuilder.newBuilder().expireAfterWrite(20 * 60, TimeUnit.SECONDS)
			.build();
	
	public static final String KEY_TENANT_ID = "tenantId";
	public static final String KEY_USER_ID = "userId";
	public static final String KEY_LANG = "lang";
	public static final String KEY_USER_NAME = "username";
	public static final String KEY_API_KEY = "apikey";

	@Reference
	private UserService userService;

	/**
	 * 检查 apikey 的合法性，如果不合法将抛出异常，否则提取信息并设置到上下文中。
	 */
	public void checkApikey(String apikey) {
		if (apikey == null || apikey.trim().isEmpty()) {
			throw new RuntimeException("apikey is required");
		}

		User user = loadUserByApikey(apikey);
		RequestParamsHolder.setParameter(KEY_TENANT_ID, user.getTenantId());
		RequestParamsHolder.setParameter(KEY_USER_ID, user.getUserId());
		RequestParamsHolder.setParameter(KEY_LANG, user.getLanguage());
		RequestParamsHolder.setParameter(KEY_USER_NAME, user.getRealname());
		RequestParamsHolder.setParameter(KEY_API_KEY, apikey);
	}

	/**
	 * 检查 token 的合法性，如果不合法将抛出异常，否则提取信息并设置到上下文中。
	 */
	public String checkToken(String token) {
		Map<String, Object> ten = userService.verify(token);
		if (ten != null && ten.size() != 0) {
			String userId = ten.get("userId").toString();
			RequestParamsHolder.setParameter(KEY_TENANT_ID, ten.get("tenantId").toString());
			RequestParamsHolder.setParameter(KEY_USER_ID, userId);
			RequestParamsHolder.setParameter(KEY_LANG, (String) ten.get("language"));
			RequestParamsHolder.setParameter(KEY_USER_NAME, ten.get("realname").toString());
			RequestParamsHolder.setParameter(KEY_API_KEY, List.class.cast(ten.get("apiKeys")).get(0).toString());
			return userId;
		}
		return null;
	}

	/*
	 * 调用租户接口，获取 apikey 所对应的用户。
	 */
	private User loadUserByApikey(final String apikey) {
		User user = null;
		try {
			user = apikeyCache.get(apikey, () -> {
				logger.debug("try to load user by apikey: {}", apikey);
				return userService.getUserByApikey(apikey);
			});
		} catch (ExecutionException | InvalidCacheLoadException e) {
			logger.error("Failed to load user by apikey: {}", apikey);
		}
		if (user == null) {
			throw new RuntimeException("invalid apikey: " + apikey);
		}
		return user;
	}
}
